package cc.bukkitPlugin.banitem.listener;

import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;

import cc.bukkitPlugin.banitem.BanItem;
import cc.bukkitPlugin.banitem.BanItemEnume.CheckedType;
import cc.bukkitPlugin.banitem.BanItemEnume.ListType;
import cc.bukkitPlugin.banitem.check.ItemCheck;
import cc.bukkitPlugin.banitem.manager.PermissionMan;
import cc.bukkitPlugin.util.ClassUtil;
import cc.bukkitPlugin.util.config.CommentedYamlConfig;
import cc.bukkitPlugin.util.plugin.ABukkitPlugin;
import cc.bukkitPlugin.util.plugin.INeedConfig;

public class PlayerListener extends APreventListener implements INeedConfig{

    private final static boolean mHasBothHand;

    private boolean mCheckInvWhenJoin=true;
    private boolean mCheckWhenSwitchSlot=true;
    private int mCheckInvDelay=50;

    static{
        mHasBothHand=ClassUtil.isClassLoaded("org.bukkit.inventory.EquipmentSlot");
    }

    /**
     * 实例化一个玩家监听器,会自己注册到监听列表
     */
    public PlayerListener(BanItem pPlugin){
        super(pPlugin);
        this.mPlugin.registerConfigModel(this);
    }

    @Override
    public void setConfig(CommandSender pSender){
        CommentedYamlConfig tConfig=this.mPlugin.getConfigManager().getConfig();
        this.mCheckInvWhenJoin=tConfig.getBoolean("BanItem.CheckInvWhenPlayerJoin",true);
        this.mCheckWhenSwitchSlot=tConfig.getBoolean("BanItem.CheckWhenPlayerSwitchItem",true);
        this.mCheckInvDelay=tConfig.getInt("BanItem.CheckInvDelayTicks",50);
        if(this.mCheckInvDelay<0){
            this.mCheckInvDelay=0;
        }
        ABukkitPlugin.info(pSender,">玩家登陆时检查背包: "+this.mCheckInvWhenJoin);
        ABukkitPlugin.info(pSender,">玩家切换物品时检查黑名单: "+this.mCheckWhenSwitchSlot);
    }

    @EventHandler(priority=EventPriority.HIGHEST)
    public void onPlayerInteract(PlayerInteractEvent pEvent){
        Player tPlayer=pEvent.getPlayer();
        String tWorld=tPlayer.getWorld().getName();
        if(tPlayer.hasPermission("BanItem.bypass"))
            return;
        ItemCheck tItemCheck=this.getItemChecker();
        PermissionMan tPermissionMan=this.getPermissionMan();
        // 检查事件物品,是否在黑名单
        if((tCheckResult=tItemCheck.checkExist(pEvent.getItem(),tWorld,ListType.BAN)).mFind){
            if(tPermissionMan.hasPermission(tPlayer,pEvent.getItem(),ListType.BAN))
                return;

            pEvent.setCancelled(true);
            pEvent.setUseItemInHand(Event.Result.DENY);

            if(tCheckResult.mCheckedType==CheckedType.NBT&&tItemCheck.isRemoveItemFromNBT(ListType.BAN)){
                this.setCurrentItem(tPlayer,tCheckResult.mHandledItem,pEvent);
            }else if(this.mPlugin.getConfigManager().isSetNull()){
                this.setCurrentItem(tPlayer,null,pEvent);
            }else{
                this.switchSlot(tPlayer);
            }

            BanItem.send(tPlayer,tCheckResult.mReason);
            return;
        }
        // 检查事件物品,是否在禁用
        if((tCheckResult=tItemCheck.checkExist(pEvent.getItem(),tWorld,ListType.USE)).mFind){
            if(tPermissionMan.hasPermission(tPlayer,pEvent.getItem(),ListType.USE))
                return;

            pEvent.setCancelled(true);
            pEvent.setUseItemInHand(Event.Result.DENY);

            if(tCheckResult.mCheckedType==CheckedType.NBT&&tItemCheck.isRemoveItemFromNBT(ListType.USE)){
                this.setCurrentItem(tPlayer,tCheckResult.mHandledItem,pEvent);
            }else this.switchSlot(tPlayer);
            BanItem.send(tPlayer,tCheckResult.mReason);
            return;
        }
        // 检查事件方块
        if((tCheckResult=tItemCheck.checkExist(pEvent.getClickedBlock(),tWorld,ListType.BAN)).mFind){
            if(tPermissionMan.hasPermission(tPlayer,pEvent.getClickedBlock()))
                return;

            pEvent.setCancelled(true);
            pEvent.setUseInteractedBlock(Event.Result.DENY);

            if(tCheckResult.mCheckedType==CheckedType.NBT)
                BanItem.send(tPlayer,"该容器包含黑名单物品,你不能和该容器交互");
            else BanItem.send(tPlayer,tCheckResult.mReason);
            return;
        }

    }

    protected void setCurrentItem(Player pPlayer,ItemStack pItem,PlayerInteractEvent pEvent){
        if(pItem!=null&&(pItem.getType()==Material.AIR||pItem.getAmount()<=0)){
            pItem=null;
        }
        
        if(PlayerListener.mHasBothHand){
            try{
                if(pEvent.getHand()==EquipmentSlot.HAND){
                    pPlayer.getInventory().setItemInMainHand(pItem);
                }else{
                    pPlayer.getInventory().setItemInOffHand(pItem);
                }
                return ;
            }catch(Throwable exp){
                BanItem.severe("没收物品时发生了错误: "+exp.getMessage(),exp);
                return ;
            }
        }else{
            pPlayer.setItemInHand(pItem);
        }
        
        
    }

    @EventHandler(priority=EventPriority.HIGHEST)
    public void onPlayerClickInv(InventoryClickEvent pEvent){
        Player tPlayer=(Player)pEvent.getWhoClicked();
        String tWorld=tPlayer.getWorld().getName();
        if(tPlayer.hasPermission("BanItem.bypass"))
            return;
        ItemCheck tItemCheck=this.getItemChecker();
        PermissionMan tPermissionMan=this.getPermissionMan();
        if((tCheckResult=tItemCheck.checkExist(pEvent.getCurrentItem(),tWorld,ListType.BAN)).mFind){
            if(tPermissionMan.hasPermission(tPlayer,pEvent.getCurrentItem(),ListType.BAN))
                return;
            pEvent.setCancelled(true);
            if(tCheckResult.mCheckedType==CheckedType.NBT&&this.getItemChecker().isRemoveItemFromNBT(ListType.BAN)){
                pEvent.setCurrentItem(tCheckResult.mHandledItem);
            }else if(this.mPlugin.getConfigManager().isSetNull()){
                pEvent.setCurrentItem(new ItemStack(Material.AIR,1));
            }
            BanItem.send(tPlayer,tCheckResult.mReason);
            return;
        }
        if((tCheckResult=tItemCheck.checkExist(pEvent.getCursor(),tWorld,ListType.BAN)).mFind){
            if(tPermissionMan.hasPermission(tPlayer,pEvent.getCursor(),ListType.BAN))
                return;
            pEvent.setCancelled(true);
            if(tCheckResult.mCheckedType==CheckedType.NBT&&tItemCheck.isRemoveItemFromNBT(ListType.BAN)){
                pEvent.setCursor(tCheckResult.mHandledItem);
            }else if(this.mPlugin.getConfigManager().isSetNull()){
                pEvent.setCursor(new ItemStack(Material.AIR,1));
            }
            BanItem.send(tPlayer,tCheckResult.mReason);
            return;
        }
    }

    @EventHandler(priority=EventPriority.HIGHEST)
    public void onPlayerPickupItem(PlayerPickupItemEvent pEvent){
        Player tPlayer=pEvent.getPlayer();
        String tWorld=tPlayer.getWorld().getName();
        if(tPlayer.hasPermission("BanItem.bypass"))
            return;
        if((tCheckResult=this.getItemChecker().checkExist(pEvent.getItem().getItemStack(),tWorld,ListType.BAN)).mFind){
            if(this.getPermissionMan().hasPermission(tPlayer,pEvent.getItem().getItemStack(),ListType.BAN))
                return;
            pEvent.setCancelled(true);
            if(this.mPlugin.getConfigManager().isSetNull())
                pEvent.getItem().remove();
            BanItem.send(tPlayer,tCheckResult.mReason);
        }
    }

    @EventHandler(priority=EventPriority.HIGHEST)
    public void onPlayerSwitchSlot(PlayerItemHeldEvent pEvent){
        if(!this.mCheckWhenSwitchSlot)
            return;
        ItemStack tItem=pEvent.getPlayer().getInventory().getItem(pEvent.getNewSlot());
        Player tPlayer=pEvent.getPlayer();
        if(tItem==null||tItem.getType()==Material.AIR)
            return;
        if(tPlayer.hasPermission("BanItem.bypass"))
            return;
        ItemCheck tItemCheck=this.getItemChecker();
        if((tCheckResult=tItemCheck.checkExist(tItem,tPlayer.getWorld().getName(),ListType.BAN)).mFind){
            if(this.getPermissionMan().hasPermission(tPlayer,tItem,ListType.BAN))
                return;
            pEvent.setCancelled(true);
            if(tCheckResult.mCheckedType==CheckedType.NBT&&tItemCheck.isRemoveItemFromNBT(ListType.BAN)){
                tPlayer.getInventory().setItem(pEvent.getNewSlot(),tCheckResult.mHandledItem);
            }else if(this.mPlugin.getConfigManager().isSetNull()){
                tPlayer.getInventory().setItem(pEvent.getNewSlot(),null);
            }
            BanItem.send(tPlayer,tCheckResult.mReason);
        }
    }

    @EventHandler(priority=EventPriority.HIGHEST)
    public void onPlayerJoin(PlayerJoinEvent pEvent){
        if(!this.mCheckInvWhenJoin)
            return;
        final Player tPlayer=pEvent.getPlayer();
        if(tPlayer==null)
            return;
        //使用任务延迟执行,防止崩掉客户端
        Bukkit.getScheduler().scheduleSyncDelayedTask(this.mPlugin,new Runnable(){

            @Override
            public void run(){
                PlayerListener.this.getItemChecker().checkPlayerInv(tPlayer,null);
            }
        },this.mCheckInvDelay);
    }

}
